package com.xd.common.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.xd.common.exception.XkdException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;

@Component
public class WeChatPayUtil {

    public static PrivateKey getPrivateKey(String filename) throws IOException {
        String absolutePath = FileUtil.getAbsolutePath(filename);//获取绝对路径

        String content = new String(Files.readAllBytes(Paths.get(absolutePath)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }


    public static CloseableHttpClient getHttpClient(String merchantId,String merchantSerialNumber,PrivateKey privateKey,String apiV3Key) throws NotFoundException, GeneralSecurityException, IOException, HttpCodeException {
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
                new PrivateKeySigner(merchantSerialNumber, privateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息

        // 从证书管理器中获取verifier
        Verifier verifier = certificatesManager.getVerifier(merchantId);
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNumber, privateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }


    //下单接口
    public static Object nativePath(CloseableHttpClient httpClient, String url, String merchantId, String appId, String description, String notifyUrl, String outTradeNo, int total, Integer companyId, String rechargeType, String code, int counts) throws IOException {
        String format = DateUtil.format(DateUtil.offsetMinute(DateUtil.date(), +5), "yyyy-MM-dd'T'HH:mm:ssXXX");//5分钟过期
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();

        //自定义
        HashMap<String, Object> map = new HashMap<>();
        map.put("companyId", companyId);
        map.put("rechargeType",rechargeType);
        map.put("code",code);
        map.put("smsCounts",counts);//短信/渠道包数量
        String userDetail = JSONObject.toJSONString(map);

        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid",merchantId)
                .put("appid", appId)
                .put("description", description)
                .put("notify_url", notifyUrl)
                .put("out_trade_no", outTradeNo)
                .put("time_expire", format)
                .put("attach", userDetail);
        rootNode.putObject("amount")
                .put("total",total*100);
        objectMapper.writeValue(bos, rootNode);

        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPost);
        String s = EntityUtils.toString(response.getEntity());
        JSONObject jsonObject = JSONObject.parseObject(s);
        if(jsonObject.get("code") != null){
            if (("PARAM_ERROR").equalsIgnoreCase(jsonObject.get("code").toString()))
                throw new XkdException("参数错误");
            if (("INVALID_REQUEST").equalsIgnoreCase(jsonObject.get("code").toString()))
                throw new XkdException("HTTP 请求不符合微信支付 APIv3 接口规则");
            if (("SIGN_ERROR").equalsIgnoreCase(jsonObject.get("code").toString()))
                throw new XkdException("验证不通过");
            if (("SYSTEM_ERROR").equalsIgnoreCase(jsonObject.get("code").toString()))
                throw new XkdException("系统异常，请稍后重试");
        }
        return jsonObject;
    }

    //查询订单
    public static String orderPath(CloseableHttpClient httpClient,String url,String outTradeNo,String merchantId) throws URISyntaxException, IOException {

        URIBuilder uriBuilder = new URIBuilder(url+"/"+outTradeNo+"?mchid="+merchantId);
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        String s = EntityUtils.toString(response.getEntity());
        JSONObject jsonObject = JSONObject.parseObject(s);
        if (jsonObject.get("trade_state") ==null){
            throw new XkdException("查看订单失败");
        }
        String tradeState = (String) jsonObject.get("trade_state");
        return tradeState;
    }

    //关闭订单
    public static void close(CloseableHttpClient httpClient,String url,String outTradeNo,String merchantId) throws URISyntaxException, IOException {

        HttpPost httpPost = new HttpPost(url+"/"+outTradeNo+"/close");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();

        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid",merchantId);
        objectMapper.writeValue(bos, rootNode);
        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        httpClient.execute(httpPost);
    }

    public static void main(String[] args) {
        String dada = "2023-07-13T13:45:24+08:00";
        DateTime parse = DateUtil.parse(dada);
        System.out.println(parse);
    }

}
